#include "Task.hh"
int Next =0;
#define TaskCount 5
class Pipe
{
public:
    Pipe(int wfd,const std::string& name,pid_t SubProcessid)
    :_wfd(wfd),_name(name),_SubProcessid(SubProcessid)
    {}
    ~Pipe(){}
    int GetWfd()
    {return _wfd;}
    std::string GetName()
    {return _name;}
    pid_t GitSubProcessid()
    {return _SubProcessid;}
    void PipeClose()
    {
        close(_wfd);
    }
    void WaitSub()
    {
        pid_t pid =waitpid(_SubProcessid,nullptr,0);
        if(pid<0)
        exit(12);
        else
        std::cout<<"wait success"<<std::endl;
    }
private:

    int _wfd;
    std::string _name;
    pid_t _SubProcessid;

};

void CreatSubProceeAndPipe(std::vector<Pipe>* Pipes,int num,task_t work)
{
    for(int i =0;i<num;i++)
    {
        int pipefd[2]={0};
        int n=pipe(pipefd);
        if(n<0)
        return exit(11);
        pid_t pid=fork();
        if(pid<0)
        exit(12);
        if(pid==0)//子进程
        {
            close(pipefd[1]);
            dup2(pipefd[0],0);
            std::cout<<"子进程: "<<i<<"working!"<<std::endl;
            work();
             std::cout<<"子进程: "<<i<<"work finish!"<<std::endl;
            close(pipefd[0]);
            exit(0);
        }
        close(pipefd[0]);//父进程关闭读端
        std::string  w_name ="WPipe-";
        w_name+=i+'0';
        Pipes->push_back({pipefd[1],w_name,pid});

    }

}
void CtrlSubProcess(std::vector<Pipe>& Pipes,int taskcount)
{
    while (taskcount--)
    {
        int n =rand()%TaskNum;//随机选一个任务
        int m =Next%Pipes.size();//平均分发给每个进程
        Next++;
        std::cout<<"正在向"<<Pipes[m].GetName()<<"写入任务代码"<<std::endl;
        write(Pipes[m].GetWfd(),&n,4);//写入管道所要执行任务任务代码（也就是tasks的数组下标）
        std::cout<<"写入完毕"<<std::endl;
    }
}
void CleanSubpProcessAndPipe(std::vector<Pipe>& Pipes)
{
    for(auto &e:Pipes)
    e.PipeClose();
    for(auto &e:Pipes)
    e.WaitSub();
};
int main(int argc ,char* argv[])
{
    if(argc==2)
    {
        LoadTask();
        int num =std::stoi(argv[1]);
        std::vector<Pipe> Pipes;
        //创建管道和子进程
        CreatSubProceeAndPipe(&Pipes,num,work);
        //通过管道给子进程分发任务
        CtrlSubProcess(Pipes,TaskCount);
        //清理工作
        CleanSubpProcessAndPipe(Pipes);

    }
    else
    return 10;
}

